package com.recipedb.sprint.service.impl;

import com.recipedb.sprint.entity.Rewards;
import com.recipedb.sprint.entity.Users;
import com.recipedb.sprint.repository.PointsRewardsRepository;
import com.recipedb.sprint.repository.RewardsRepository;
import com.recipedb.sprint.repository.UsersRepository;
import com.recipedb.sprint.repository.PointRecordsRepository;
import com.recipedb.sprint.service.RewardsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class RewardsServiceImpl implements RewardsService {

    private final RewardsRepository rewardsRepository;
    private final PointsRewardsRepository pointsRewardsRepository;
    private final PointRecordsRepository pointRecordsRepository;
    private final UsersRepository usersRepository;

    public RewardsServiceImpl(RewardsRepository rewardsRepository,
                              PointsRewardsRepository pointsRewardsRepository,
                              PointRecordsRepository pointRecordsRepository,
                              UsersRepository usersRepository) {
        this.rewardsRepository = rewardsRepository;
        this.pointsRewardsRepository = pointsRewardsRepository;
        this.pointRecordsRepository = pointRecordsRepository;
        this.usersRepository = usersRepository;
    }

    @Override
    @Transactional
    public Map<String, Object> redeemReward(Long userid, Long rewardId, Integer quantity) {
        System.out.println("=== 兑换开始 ===");
        System.out.println("用户ID: " + userid + ", 奖品ID: " + rewardId + ", 数量: " + quantity);

        try {
            // 1. 基础验证（只检查奖品是否存在）
            Rewards reward = rewardsRepository.findById(rewardId)
                    .orElseThrow(() -> new RuntimeException("奖品不存在"));
            System.out.println("✅ 奖品: " + reward.getName() + ", 库存: " + reward.getStock());

            // 2. 直接调用存储过程（所有业务逻辑在数据库中完成）
            System.out.println("调用存储过程 redeem_reward...");
            pointRecordsRepository.redeemReward(userid, rewardId, quantity);
            System.out.println("✅ 存储过程调用成功");

            // 3. 返回成功结果
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("rewardId", reward.getRewardId());
            result.put("rewardName", reward.getName());
            result.put("quantity", quantity);
            result.put("pointsSpent", reward.getPointsRequired() * quantity);
            result.put("message", "兑换成功");

            System.out.println("=== 兑换完成 ===");
            return result;

        } catch (Exception e) {
            System.out.println("❌ 兑换异常: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("兑换失败: " + e.getMessage());
        }
    }

    // 以下方法保持不变
    @Override
    public Long getUserIdByUsername(String username) {
        return usersRepository.findByUsername(username)
                .map(Users::getUserid)
                .orElseThrow(() -> new RuntimeException("用户不存在：" + username));
    }

    @Override
    public List<Map<String, Object>> getAvailableRewards() {
        List<Rewards> rewards = rewardsRepository.findByStockGreaterThanOrderByPointsRequiredAsc(0);

        return rewards.stream()
                .map(this::convertRewardToMap)
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> getRewardDetail(Long rewardId) {
        Rewards reward = rewardsRepository.findById(rewardId)
                .orElseThrow(() -> new RuntimeException("奖品不存在"));

        Map<String, Object> detail = convertRewardToMap(reward);
        detail.put("createdAt", reward.getCreatedAt());
        return detail;
    }

    private Map<String, Object> convertRewardToMap(Rewards reward) {
        Map<String, Object> map = new HashMap<>();
        map.put("rewardId", reward.getRewardId());
        map.put("name", reward.getName());
        map.put("description", reward.getDescription());
        map.put("pointsRequired", reward.getPointsRequired());
        map.put("stock", reward.getStock());
        return map;
    }
}